package com.jjjjbababy.rulerviewdemo

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
import android.widget.OverScroller
import androidx.core.content.ContextCompat
import androidx.core.graphics.withSave
import androidx.core.view.ViewCompat
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

/**
 * Created by helu on 2022/4/27.
 * Description:
 */
class RulerView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val shortPaint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = ContextCompat.getColor(context, android.R.color.holo_blue_bright)
            strokeWidth = shortLineWidth
        }
    }

    private val longPaint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = ContextCompat.getColor(context, android.R.color.holo_blue_bright)
            strokeWidth = longLineWidth
        }
    }

    private val textPaint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = ContextCompat.getColor(context, android.R.color.black)
            textSize = 14.dp
            textAlign = Paint.Align.CENTER
        }
    }

    private val midPaint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = ContextCompat.getColor(context, android.R.color.holo_blue_dark)
            strokeWidth = longLineWidth
        }
    }

    private val shortLineHeight = 20.dp
    private val longLineHeight = 30.dp
    private val shortLineWidth = 1.dp
    private val longLineWidth = 2.dp
    private val mGap = 10.dp
    private val mGapCount = 130
    private var screenW = DisplayUtil.getScreenWidth(context)
    private var totalWidth = 0f
    private var scaledMinimumFlingVelocity = ViewConfiguration.get(context).scaledMinimumFlingVelocity.toFloat()
    private var scaledMaximumFlingVelocity = ViewConfiguration.get(context).scaledMaximumFlingVelocity.toFloat()
    private val overScroller = OverScroller(context)
    private val runnable = ScrollerRunnable()
    private val velocityTracker = VelocityTracker.obtain()
    var callback : ((Int) -> Unit?)? = null

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        totalWidth = screenW + mGap * mGapCount
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        setMeasuredDimension(totalWidth.toInt(), heightSize)
    }

    override fun onDraw(canvas: Canvas) {
        canvas.drawColor(ContextCompat.getColor(context,android.R.color.holo_green_light))
        canvas.withSave {
//            canvas.drawLine((screenW - longLineWidth)/2,0f,(screenW - longLineWidth)/2,longLineHeight,midPaint)
            for(index in 0..(mGapCount/10)){
                canvas.drawLine(screenW/2 + 10 * mGap * index,
                    0f,
                    screenW/2 + 10 * mGap * index,
                    longLineHeight,
                    longPaint)
                val text = (100+index*10).toString()
                canvas.drawText(text,
                    screenW/2 + 10 * mGap * index,
                    longLineHeight + 2 * (textPaint.fontMetrics.bottom - textPaint.fontMetrics.top),
                       textPaint)
            }
            for(index in 0..mGapCount){
                canvas.drawLine(screenW/2  + mGap * index,
                0f,
                    screenW/2 + mGap * index,
                shortLineHeight,
                shortPaint)
            }
        }
    }

    private var downX = 0f
    private var originX = 0f
    private var offsetX = 0f

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            velocityTracker.clear()
        }
        velocityTracker.addMovement(event)
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                downX = event.x
                originX = offsetX
                if (!overScroller.isFinished) {
                    overScroller.abortAnimation()
                }
            }
            MotionEvent.ACTION_MOVE -> {
                offsetX = event.x - downX + originX
                offsetX = min(offsetX,0f)
                offsetX = max(offsetX,-mGap * mGapCount)
                scrollTo((-offsetX).toInt(),0)
                callback?.invoke((abs(offsetX) / 10.dp).toInt() + 100)
            }
            MotionEvent.ACTION_UP -> {
                velocityTracker.computeCurrentVelocity(1000, scaledMaximumFlingVelocity)
                val xVelocity = velocityTracker.xVelocity
                if(abs(xVelocity) > scaledMinimumFlingVelocity){
                    overScroller.fling(
                        offsetX.toInt(),
                        0,
                        xVelocity.toInt(),
                        0,
                        (-mGap * mGapCount).toInt(),
                        0,
                        0,
                        0)
                    ViewCompat.postOnAnimation(this,runnable)
                }
            }
        }
        return true
    }

    inner class ScrollerRunnable :Runnable{
        override fun run() {
            if (overScroller.computeScrollOffset()) {
                offsetX = overScroller.currX.toFloat()
                scrollTo(-overScroller.currX,0)
                callback?.invoke((abs(offsetX) / 10.dp).toInt()+ 100)
                postOnAnimation(this)
            }
        }
    }

    override fun onDetachedFromWindow() {
        velocityTracker.recycle()
        super.onDetachedFromWindow()
    }
}